#pragma once


#include "stdafx.h"

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CBoundingSphere
{
public:
	D3DXVECTOR3			m_vPos;
	float				m_fRadius;
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class CBoundingBox
{
public:
	D3DXVECTOR3			m_vMinimum;
	D3DXVECTOR3			m_vMaximum;

	void Transform(D3DXMATRIX* pmtxTransdform);
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define FVF_XYZD	( D3DFVF_XYZ | D3DFVF_DIFFUSE )
class CVertex
{
public:
    CVertex(float x, float y, float z, DWORD dwColor) { m_vPosition = D3DXVECTOR3(x, y, z); m_dwDiffuse = dwColor; }
    CVertex() { m_vPosition = D3DXVECTOR3(0.0f, 0.0f, 0.0f); m_dwDiffuse = D3DCOLOR_XRGB(0, 0, 0xff); }

    D3DXVECTOR3				m_vPosition;  
	DWORD					m_dwDiffuse;   
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define FVF_XYZT	( D3DFVF_XYZ | D3DFVF_TEX1)

class CVertexT1
{
public:
	CVertexT1()
	{
		m_vPosition	=	D3DXVECTOR3(0.0f, 0.0f, 0.0f);
		m_vTexture1 =	D3DXVECTOR2( 0.0f, 0.0f);
	}
	CVertexT1(const D3DXVECTOR3& vPosition, const D3DXVECTOR2& vTexture1)
	{
		m_vPosition = vPosition;
		m_vTexture1 = vTexture1;
	}
public:
	D3DXVECTOR3			m_vPosition;
	D3DXVECTOR2			m_vTexture1;
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define FVF_XYZT2N	( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX2)

class CVertexT2N
{
public:
	CVertexT2N(const D3DXVECTOR3& vPosition,const D3DXVECTOR3& vNormal
		,const D3DXVECTOR2& vTexture1, const D3DXVECTOR2& vTexture2)
	{
		m_vPosition = vPosition;	m_vNormal = vNormal;
		m_vTexture1 = vTexture1;	m_vTexture2 = vTexture2;
	}
	CVertexT2N()
	{
		m_vNormal	=	m_vPosition	=	D3DXVECTOR3(0.0f, 0.0f, 0.0f);
		m_vTexture1	=	m_vTexture2 =	D3DXVECTOR2( 0.0f, 0.0f);
	}
public:
	D3DXVECTOR3			m_vPosition;
	D3DXVECTOR3			m_vNormal;
	D3DXVECTOR2			m_vTexture1;
	D3DXVECTOR2			m_vTexture2;
};















//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CBaseMesh
{
private:
	int						m_nReferences;

protected:
	CBoundingBox			m_bbBoundingBox;
	CBoundingSphere			m_bsBoundingSphere;

	DWORD					m_dwFVF;

public:
	CBaseMesh()	:m_nReferences(0)	{	}
	virtual ~CBaseMesh()			{	}
		
	void AddRef()			{ m_nReferences++; }
	void Release()			{ m_nReferences--; if (!m_nReferences) delete this; }

	CBoundingBox			GetBoundingBox()		{	return m_bbBoundingBox;	}
	CBoundingSphere			GetBoundingSphere()		{	return m_bsBoundingSphere;	}

	virtual void Render( LPDIRECT3DDEVICE9 pD3DDevice) = 0;
	virtual bool IntersectTriangle(D3DXVECTOR3* vPos,D3DXVECTOR3* vDir,float* pfU,float* pfV, float* pfDist) = 0;
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CMesh :public CBaseMesh
{
private:
	int						m_nVertexCount;     
    CVertex					*m_pVertex;   
	
public:
	CMesh(int nVertexCount, DWORD dwFVF);
	virtual ~CMesh();

	void Build();
	virtual void Render( LPDIRECT3DDEVICE9 pD3DDevice);
	virtual bool IntersectTriangle(D3DXVECTOR3* vPos,D3DXVECTOR3* vDir,float* pfU,float* pfV, float* pfDist);
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

class CXMesh :public CBaseMesh
{
protected:
	LPDIRECT3DTEXTURE9			m_pd3dTexture;   
	D3DMATERIAL9				*m_pd3dMaterial;
    LPD3DXMESH					m_pd3dxMesh; 
	DWORD						m_nAttributes;
public:
	CXMesh();
    virtual ~CXMesh();
	
	void ComputeBoundingSphere();
	void ComputeBoundingBox();
	bool LoadFromXFile(LPCTSTR lpstrFileName, DWORD dwOptions, LPDIRECT3DDEVICE9 pD3DDevice);
	virtual void Render(LPDIRECT3DDEVICE9 pD3DDevice);
	virtual bool IntersectTriangle(D3DXVECTOR3* vPos,D3DXVECTOR3* vDir,float* pfU,float* pfV, float* pfDist);
};


//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////